package svc.elib.lookup;

import java.util.Collections;
import java.util.LinkedList;

import com.aliasi.spell.JaccardDistance;
import com.aliasi.spell.JaroWinklerDistance;
import com.aliasi.tokenizer.IndoEuropeanTokenizerFactory;
import com.aliasi.tokenizer.TokenizerFactory;


public abstract class NameSimilarity {

	public class SignificantSimilarity implements Comparable<SignificantSimilarity> {

		String s1, s2;
		double score;
		
    	public SignificantSimilarity(String s1, String s2, double score) {
    		this.s1 = s1;
    		this.s2 = s2;
    		this.score = score;
    	}
    	
		@Override
		public int compareTo(SignificantSimilarity another) {
			if (this.score > another.score)
				return -1;
			else
			if (this.score < another.score)
				return 1;
			else
				return 0;
		}
		
		public String toString() {
			return score + ", |" + s1 + "|, |" + s2 + "|";
		}
    }
	
	protected JaccardDistance jaccard;
	protected JaroWinklerDistance jaroWinkler = JaroWinklerDistance.JARO_WINKLER_DISTANCE;
	protected LinkedList<SignificantSimilarity> jaccardResults;
	protected LinkedList<SignificantSimilarity> jaroResults;

	
	public NameSimilarity() {
		TokenizerFactory tokenizerFactory = IndoEuropeanTokenizerFactory.INSTANCE;
        jaccard = new JaccardDistance(tokenizerFactory);
        jaccardResults = new LinkedList<SignificantSimilarity>();
        jaroResults = new LinkedList<SignificantSimilarity>(); 
	}
	
	protected void checkSimilar(LinkedList<String> names) {
		for (int i = 1; i < names.size(); i++) {
			for (int j = 0; j < i; j++) {
				String s1 = names.get(i);
				String s2 = names.get(j);
			
				double jd = jaccard.proximity(s1, s2);
				if (jd > 0.6 && !exclude(s1, s2))
					jaccardResults.add(new SignificantSimilarity(s1, s2, jd));
				
				jd = jaroWinkler.proximity(s1, s2);
				if (jd > 0.9 && !exclude(s1, s2))
					jaroResults.add(new SignificantSimilarity(s1, s2, jd));
			}
		}
	}
	
	private boolean exclude(String s1, String s2) {
		String s1e = s1.substring(s1.indexOf("_") + 1);
		String s2e = s2.substring(s2.indexOf("_") + 1);
		s1e = s1e.replace(".", "").replace(" ", "");
		s2e = s2e.replace(".", "").replace(" ", "");
	
		if (s1e.length() == s2e.length() && s1e.length() <= 2 && s1e.compareTo(s2e) != 0)
			return true;
		
		return false;
	}
	
	protected void dumpResults() {
		Collections.sort(jaccardResults);
		System.out.println("Jaccard distance... ");
		printSignificantList(jaccardResults);
		
		Collections.sort(jaroResults);
		System.out.println("\n\n\nJaroWinkler distance... ");
		printSignificantList(jaroResults);
	}
	
	protected void printSignificantList(LinkedList<SignificantSimilarity> list) {
		for (SignificantSimilarity s : list) {
			System.out.println(s.toString());
		}
	}
}
